/**
 * AT24C02 / AT24C02N, 几毛钱1个
 * 是一种可以实现掉电不丢失的存储器，可用于保存单片机运行时想要永久保存的数据信息
 * 存储介质：E2PROM (Electrically Erasable Programmable Read Only Memory)
 * 通讯接口：I2C总线
 * 容量：256字节
 * 电源（1.8V~5.5V ）
 * IIC时钟频率: 1MHz(5V),  400KHz(1.8V, 2.5V, 2.7V)
 * 内部写周期(最大5ms内即可完成擦除&写的操作)
 * 
 * AT24C02: 2K位 / 8 = 256Byte
 * AT24C04: 4K位 / 8 = 512Byte
 * AT24C08: 8K位 / 8 = 1Kb
 * AT24C16: 16K位 / 8 = 2Kb
 * AT24C32: 32K位 / 8 = 4Kb
 * AT24C64: 64K位 / 8 = 8Kb
 */
#include "Delay_Utils.h"
#include "I2C_Bus_Utils.h"

/**
 * AT24C02的固定地址为1010，可配置地址(A2,A1,A0)本开发板上为000 (接地)
 * 所以SLAVE ADDRESS+W 为 0xA0 (W写低电平有效)(1010 000 0)
 * SLAVE ADDRESS+R 为 0xA1     (R读高电平有效)(1010 000 1)
 */
#define AT24C02_ADDRESS_WRITE 0xA0
#define AT24C02_ADDRESS_READ  0xA1

/**
 * 写入1个字节：在WORD ADDRESS处写入数据DATA
 * 
 * @param WordAddress 要写入字节的地址, if是 256Byte, 取值范围就是: 0~255
 * @param Data 写入的1个字节
 * @param isDelay5ms 是否延时5ms. ∵写周期最大5ms, I2C_Stop() 后, 要隔5ms才能继续 读/写 操作.
 * @return 是否发送成功, 0成功, 1失败
 */
bit AT24C02_WriteByte(unsigned char WordAddress, unsigned char Data, bit isDelay5ms) {
    bit acknowledge;
    I2C_Start();
    I2C_SendByte(AT24C02_ADDRESS_WRITE);
    //接收应答
    acknowledge = I2C_ReceiveAck();
    //如果没接收到应答
    if (acknowledge) goto STOP;
    //2.发送地址, 要把数据写入到哪个地址
    I2C_SendByte(WordAddress);
    acknowledge = I2C_ReceiveAck();
    if (acknowledge) goto STOP;
    //3.发送数据
    I2C_SendByte(Data);
    acknowledge = I2C_ReceiveAck();
    // if (acknowledge) goto STOP;
    STOP:
    I2C_Stop();
    if (!acknowledge && isDelay5ms) Delayms(5);
    return acknowledge;
}

/**
 * 读出1个字节：随机读：读出在WORD ADDRESS处的数据DATA
 * @param WordAddress 要读取字节的地址, if是 256Byte, 取值范围就是: 0~255
 * @return 读出的1个字节
 */
unsigned char AT24C02_ReadByte(unsigned char WordAddress) {
    unsigned char Data = 0;
    bit acknowledge;
    I2C_Start();
    I2C_SendByte(AT24C02_ADDRESS_WRITE);
    //接收应答
    acknowledge = I2C_ReceiveAck();
    //如果没接收到应答
    if (acknowledge) goto STOP;
    //2.发送地址, 要把数据写入到哪个地址
    I2C_SendByte(WordAddress);
    acknowledge = I2C_ReceiveAck();
    if (acknowledge) goto STOP;
    //3.接收数据
    I2C_Start();
    I2C_SendByte(AT24C02_ADDRESS_READ);
    acknowledge = I2C_ReceiveAck();
    if (acknowledge) goto STOP;
    Data = I2C_ReceiveByte();
    //发送应答
    I2C_SendAck(1);
    STOP:
    I2C_Stop();
    return Data;
}